home *** CD-ROM | disk | FTP | other *** search
/ Linux Cubed Series 7: Sunsite / Linux Cubed Series 7 - Sunsite Vol 1.iso / system / filesyst / dosfs / dmsdosfs.000 / dmsdosfs / dmsdosfs-0.6.9b / dmsdos_read.c < prev    next >
C/C++ Source or Header  |  1996-07-29  |  23KB  |  795 lines

  1. /*
  2. linux/fs/dmsdos/dmsdos_read.c
  3.  
  4. DMSDOS filesystem: read access routines.
  5.  
  6. ******************************************************************************
  7. DMSDOS (Doublespace/Drivespace compressed MSDOS filesystem) for Linux
  8. written 1995,1996 by Frank Gockel
  9.  
  10.     (C) Copyright 1995,1996 by Frank Gockel
  11.  
  12. Some code of the dmsdos filesystem has been copied from the msdos filesystem
  13. so there are the following additional copyrights:
  14.  
  15.     (C) Copyright 1992,1993 by Werner Almesberger (msdos filesystem)
  16.     (C) Copyright 1994,1995 by Jacques Gelinas (mmap code)
  17.     (C) Copyright 1992-1995 by Linus Torvalds
  18.  
  19. The DMSDOS filesystem was inspired by the THS filesystem (a simple doublespace
  20. DS-0-2 compressed read-only filesystem) written 1994 by Thomas Scheuermann.
  21.  
  22. The DMSDOS filesystem is distributed under the Gnu General Public Licence.
  23. See file COPYING for details.
  24. ******************************************************************************
  25.  
  26. */
  27.  
  28. #include <linux/sched.h>
  29. #include <linux/ctype.h>
  30. #include <linux/major.h>
  31. #include <linux/blkdev.h>
  32. #include <linux/fs.h>
  33. #include <linux/stat.h>
  34. #include <linux/locks.h>
  35. #include <asm/segment.h>
  36. #include <linux/mm.h>
  37. #include <linux/malloc.h>
  38. #include <linux/string.h>
  39. #include <linux/msdos_fs.h>
  40. #include <linux/dmsdos_fs.h>
  41. #include <linux/errno.h>
  42. #include <linux/kernel.h>
  43. #include <linux/shm.h>
  44. #include <linux/mman.h>
  45. #include <asm/system.h>
  46.  
  47. #define PRINTK(X)
  48. #define CLPOS 26
  49.  
  50. extern int dbl_cvf_inos[];
  51. extern Dblsb dblsb[];
  52.  
  53. /* returns ino or -ENOENT */
  54. /* must not break on empty/zero entries */
  55. int read_dbl_direntry(struct super_block*sb,
  56.                       int dbl_clusterno,int cvfnr,int entrynr,
  57.                       unsigned char*buf)
  58. { int dbl_sector;
  59.   int dbl_offset;
  60.   int ino;
  61.   struct buffer_head*bh;
  62.   int i;
  63.   Mdfat_entry mde;
  64.   
  65.   /* Hmm ...  error test: */
  66.   if(entrynr>65535*16*dblsb[cvfnr].s_sectperclust)
  67.   { /* impossible, there are max 65535 clusters a 16*sectperclust entries */
  68.     /* this is most likely a fat loop (code prevents hang) */
  69.     printk("DMSDOS: read_dbl_direntry: entrynr too large, aborting!\n");
  70.     return -ENOENT;
  71.   }
  72.   
  73.   /* get sector and offset */
  74.   if(dbl_clusterno==0) /*it is a dbl rootdir*/
  75.   { dbl_sector=dblsb[cvfnr].s_rootdir+(entrynr>>4);
  76.     if(entrynr>=dblsb[cvfnr].s_rootdiranzentry)return -ENOENT;
  77.   }
  78.   else
  79.   { while(entrynr/(16*dblsb[cvfnr].s_sectperclust))
  80.     { entrynr-=(16*dblsb[cvfnr].s_sectperclust);
  81.       dbl_clusterno=dbl_fat_nextcluster(sb,dbl_clusterno,cvfnr,NULL);
  82.       if(dbl_clusterno==-1)return -ENOENT;
  83.       if(entrynr<0)
  84.       { printk("DMSDOS: read_dbl_direntry: error calculating clusterno\n");
  85.         return -ENOENT;
  86.       }
  87.     }
  88.     
  89.     dbl_mdfat_value(sb,dbl_clusterno,cvfnr,NULL,&mde);
  90.     
  91.     /* handle compressed directory clusters under drivespace 3 */  
  92.     if((mde.flags&1)==0&&64==dblsb[cvfnr].s_sectperclust)
  93.     { printk("DMSDOS: read_dbl_direntry: compressed drivespace 3 directory cluster, can't read!"
  94.              " clusternr=%d flags=%d sizehi=%d cvfnr=%d\n",
  95.              dbl_clusterno,mde.flags,mde.size_hi_minus_1+1,cvfnr+1);
  96.       return -EIO;
  97.     }
  98.     
  99.     dbl_sector=mde.sector_minus_1+1; /*dbl_mdfat_cluster2sector(sb,dbl_clusterno,cvfnr);*/
  100.     /* end of shortened dir cluster reached ? */
  101.     if((entrynr>>4)>mde.size_hi_minus_1)return -ENOENT;
  102.     dbl_sector+=entrynr>>4;
  103.   }
  104.   /* always the same */
  105.   dbl_offset=entrynr&0xf;
  106.   ino=((cvfnr+1)<<DMSDOS_CVFNR_BITS)+(dbl_sector<<4)+dbl_offset;
  107.   /* read sector */
  108.   bh=read_dbl_sector(sb,dbl_sector,cvfnr);
  109.   if(bh==NULL)return -EIO;
  110.   for(i=0;i<32;++i)buf[i]=bh->b_data[i+32*dbl_offset];
  111.   bh_free(sb,bh);
  112.   return ino;
  113. }
  114.  
  115. int scan_dbl_dir_4_clusterno(struct super_block*sb,
  116.                              int dirstartclust, int tofind,int cvfnr)
  117. { int ino;
  118.   int ent=0;
  119.   unsigned char buf[32];
  120.   unsigned char * pp;
  121.  
  122.   while((ino=read_dbl_direntry(sb,dirstartclust,cvfnr,ent,buf))>0)
  123.   { ++ent;
  124.     pp=&(buf[CLPOS]);
  125.     /* break on zero entry */
  126.     if(buf[0]==0)return -ENOENT;
  127.     if(buf[0]!=0xe5&&(CHS(pp)==tofind))return ino;
  128.   }
  129.   return ino;
  130. }
  131.  
  132. /* does *not* look for . or ..
  133.    len==-1 means name is already raw msdos formatted */
  134. int scan_dbl_dir_4_filename(struct super_block*sb, int dirstartclust,
  135.                             unsigned const char*tofind,int len,
  136.                             int cvfnr)
  137. { int ino;
  138.   int ent=0;
  139.   unsigned char buf[32];
  140.   unsigned char msdosname[]="           ";
  141.   int i;
  142.   int j;
  143.   int warpunkt=0;
  144.   
  145.   if(len<0)strncpy(msdosname,tofind,11);
  146.   else
  147.   {
  148.   
  149.   for(i=0,j=0;i<len&&j<11;++i)
  150.   { if(tofind[i]=='.')
  151.     { if(j>8)return -ENOENT;
  152.       if(warpunkt)return -ENOENT;
  153.       warpunkt=1;
  154.       j=8;
  155.       continue;
  156.     }
  157.     if(tofind[i]>='a'&&tofind[i]<='z')msdosname[j++]=tofind[i]-'a'+'A';
  158.     else msdosname[j++]=tofind[i];
  159.   }
  160.   
  161.   }
  162. /*  
  163.   printk("DMSDOS: scan_dbl_dir_4_filename: name=%s dosname=%s\n",
  164.          tofind,msdosname);
  165.   printk("DMSDOS: scan_dbl_dir_4_filename: dirstartclust=%d cvfnr=%d\n",
  166.          dirstartclust,cvfnr+1);
  167. */
  168.   while((ino=read_dbl_direntry(sb,dirstartclust,cvfnr,ent,buf))>0)
  169.   { ++ent;
  170.     /* break on zero entry */
  171.     if(buf[0]==0)return -ENOENT;
  172.     if(strncmp(buf,msdosname,11)==0)
  173.     { /*printk("DMSDOS: scan_dbl_dir_4_filename: found with ino=%d\n",ino);*/
  174.       return ino;
  175.     }
  176.   }
  177. /*
  178.   printk("DMSDOS: scan_dbl_dir_4_filename: not found, error=%d, ent=%d\n",
  179.          ino,ent);
  180. */
  181.   return ino;
  182. }
  183.  
  184. /* Returns the inode number of the directory entry at offset pos.
  185.    Pos is incremented. */
  186.  
  187. int dmsdos_get_entry(struct inode *dir, loff_t *pos,unsigned char * buf)
  188. {
  189.     int entrynr;
  190.     int ino;
  191.     int clust;
  192.     int cvfnr;
  193.  
  194.         entrynr = (*pos)>>5;
  195.         *pos += 32;
  196.         if((cvfnr=dbltest(dir))!=0)cvfnr=(cvfnr>>DMSDOS_CVFNR_BITS)-1;
  197.         else cvfnr=(dir->i_ino>>DMSDOS_CVFNR_BITS)-1;
  198.         clust=MSDOS_I(dir)->i_start;/*dbl_inode2startcluster(dir);*/
  199.         ino=read_dbl_direntry(dir->i_sb,clust,cvfnr,entrynr,buf);
  200.         /* break on zero entry */
  201.         if(buf[0]==0)return -ENOENT;
  202.         return ino;
  203. }
  204.  
  205. int dmsdos_parent_ino(struct inode*dir)
  206. {  struct buffer_head*bh;
  207.    int cvfnr;
  208.    int parent_dbl_cluster;
  209.    int parent_dbl_sector;
  210.    int parent_parent_dbl_cluster;
  211.    unsigned char * pp;
  212.  
  213.    if(dbltest(dir))return MSDOS_ROOT_INO;
  214.  
  215.    cvfnr=(dir->i_ino>>DMSDOS_CVFNR_BITS)-1;
  216.    if(cvfnr<0)return -ENOENT;
  217.  
  218. /* read first sector of my own cluster */
  219.    bh=read_dbl_sector(dir->i_sb,
  220.                       dbl_mdfat_cluster2sector(dir->i_sb,
  221.                                                MSDOS_I(dir)->i_start,cvfnr),
  222.                       cvfnr);
  223.    if(bh==NULL)return -EIO;
  224. /* and get second entry (it is ..) */
  225.    pp=&(bh->b_data[32+CLPOS]);
  226.    parent_dbl_cluster=CHS(pp);
  227.    bh_free(dir->i_sb,bh);
  228.     
  229.    if(parent_dbl_cluster==0)
  230.    { /* Verweis auf dbl_rootdir */
  231.      return dbl_cvf_inos[cvfnr];
  232.    }
  233.    
  234.    parent_dbl_sector=dbl_mdfat_cluster2sector(dir->i_sb,parent_dbl_cluster,
  235.                                               cvfnr);
  236.    
  237.    bh=read_dbl_sector(dir->i_sb,parent_dbl_sector,cvfnr);
  238.    if(bh==NULL)return -EIO;
  239.    pp=&(bh->b_data[32+CLPOS]);
  240.    parent_parent_dbl_cluster=CHS(pp);
  241.    bh_free(dir->i_sb,bh);
  242.    return scan_dbl_dir_4_clusterno(dir->i_sb,
  243.                          parent_parent_dbl_cluster, /*dir start cluster*/
  244.                          parent_dbl_cluster,        /* to find */ 
  245.                          cvfnr);
  246. }
  247.  
  248. #ifdef __FOR_KERNEL_1_3
  249. /* kernel 1.3.xx needs a new readdir function .... I hope I did not break
  250.    anything in dmsdos' readdir */
  251.  
  252. int dmsdos_readdirx(
  253.     struct inode *inode,
  254.     struct file *filp,
  255.     void *dirent,
  256.     filldir_t filldir)
  257. {
  258.     int ino,i /*,i2,last*/ ;
  259.     /*char c;*/
  260.     unsigned char buf[32];
  261.     struct msdos_dir_entry *de;
  262.     unsigned long oldpos = filp->f_pos;
  263.     char longname[257];
  264.  
  265.     if (!inode || !S_ISDIR(inode->i_mode))
  266.         return -EBADF;
  267. /* Fake . and .. for the root directory. */
  268.     if (dbltest(inode)) {
  269.         while (oldpos < 2) {
  270.             if (filldir(dirent, "..", oldpos+1, oldpos, MSDOS_ROOT_INO) < 0)
  271.                 return 0;
  272.             oldpos++;
  273.             filp->f_pos++;
  274.         }
  275.         if (oldpos == 2)
  276.             filp->f_pos = 0;
  277.     }
  278.     if (filp->f_pos & (sizeof(struct msdos_dir_entry)-1))
  279.         return -ENOENT;
  280.     while ((ino = dmsdos_get_lfn_entry(inode,&filp->f_pos,buf,
  281.                                        longname)) > -1) {
  282.             de=(struct msdos_dir_entry*) buf;
  283.         if (!IS_FREE(de->name)
  284.                 /* this is copied from the new msdos readdir -
  285.                    ignore vol, ok
  286.                    ignore sys, hmm...
  287.                    but why ignore hidden ???
  288.                    well, doesn't matter, compressed ones don't
  289.                    run through this code here....
  290.                    but I do not like ignoring hidden files!
  291.                 */
  292.             && !(de->attr & (ATTR_VOLUME))) {
  293.         /*    
  294.             char bufname[12];
  295.             char *ptname = bufname;
  296.             for (i = last = 0; i < 8; i++) {
  297.                 if (!(c = de->name[i])) break;
  298.                 if (c >= 'A' && c <= 'Z') c += 32;
  299.                 if (c != ' ')
  300.                     last = i+1;
  301.                 ptname[i] = c;
  302.             }
  303.             i = last;
  304.             ptname[i] = '.';
  305.             i++;
  306.             for (i2 = 0; i2 < 3; i2++) {
  307.                 if (!(c = de->ext[i2])) break;
  308.                 if (c >= 'A' && c <= 'Z') c += 32;
  309.                 if (c != ' ')
  310.                     last = i+1;
  311.                 ptname[i] = c;
  312.                 i++;
  313.             }
  314.             if ((i = last) != 0) {
  315.         */
  316.                 i=strlen(longname);
  317.                 if(i!=0) {
  318.                 if (!strcmp(de->name,MSDOS_DOT))
  319.                     ino = inode->i_ino;
  320.                 else if (!strcmp(de->name,MSDOS_DOTDOT))
  321.                       {
  322.                     ino = dmsdos_parent_ino(inode);
  323.                     if(ino<0)return ino;
  324.                       }
  325.                 if (filldir(dirent, longname, i, oldpos, ino) < 0) {
  326.                     filp->f_pos = oldpos;
  327.                     break;
  328.                 }
  329.             }
  330.         }
  331.         oldpos = filp->f_pos;
  332.     }
  333.     return 0;
  334. }
  335.  
  336. #else
  337. /* kernel 1.2.xx readdir function */
  338.  
  339. #define NAME_OFFSET(de) ((int) ((de)->d_name - (char *) (de)))
  340. #define ROUND_UP(x) (((x)+3) & ~3)
  341.  
  342. int dmsdos_readdirx( 
  343.     struct inode *inode,
  344.     struct file *filp,
  345.     struct dirent *dirent,    /* dirent in user space */
  346.     int count)
  347. {    
  348.     int ino,i /*,i2,last*/ ;
  349.     char /*c,*/ *walk;
  350.     unsigned char buf[32];
  351.     struct msdos_dir_entry *de;
  352.     char longname[257];
  353.  
  354.     if (!inode || !S_ISDIR(inode->i_mode)) return -EBADF;
  355.     if (dbltest(inode)) {
  356.             /* printk("DMSDOS: readdirx reading dblrootdir ino=%ld\n",
  357.                                                          inode->i_ino);
  358.             */
  359. /* Fake . and .. for the root directory. */
  360.         if (filp->f_pos == 2) filp->f_pos = 0;
  361.         else if (filp->f_pos < 2) {
  362.             walk = filp->f_pos++ ? ".." : ".";
  363.             for (i = 0; *walk; walk++)
  364.                 put_fs_byte(*walk,dirent->d_name+i++);
  365.             put_fs_long(filp->f_pos==1?inode->i_ino:MSDOS_ROOT_INO,&dirent->d_ino);
  366.             put_fs_byte(0,dirent->d_name+i);
  367.             put_fs_word(i,&dirent->d_reclen);
  368.             return ROUND_UP(NAME_OFFSET(dirent) + i + 1);
  369.         }
  370.     }
  371.     /*else printk("DMSDOS: readdirx ??? ino=%ld\n",inode->i_ino);*/
  372.     if (filp->f_pos & (sizeof(struct msdos_dir_entry)-1)) return -ENOENT;
  373.  
  374.     while ((ino = dmsdos_get_lfn_entry(inode,&filp->f_pos,buf,
  375.                                        longname)) > -1) {
  376.             de=(struct msdos_dir_entry*) buf;
  377.         if (!IS_FREE(de->name) && !(de->attr & ATTR_VOLUME)) {
  378.     /*
  379.             char bufname[13];
  380.             char *ptname = bufname;
  381.             for (i = last = 0; i < 8; i++) {
  382.                 if (!(c = de->name[i])) break;
  383.                 if (c >= 'A' && c <= 'Z') c += 32;
  384.                 if (c != ' ')
  385.                     last = i+1;
  386.                 ptname[i] = c;
  387.             }
  388.             i = last;
  389.             ptname[i] = '.';
  390.             i++;
  391.             for (i2 = 0; i2 < 3; i2++) {
  392.                 if (!(c = de->ext[i2])) break;
  393.                 if (c >= 'A' && c <= 'Z') c += 32;
  394.                 if (c != ' ')
  395.                     last = i+1;
  396.                 ptname[i] = c;
  397.                                i++;
  398.             }
  399.     */
  400.             if ((i = strlen(longname)) != 0) {    
  401.                 if (!strcmp(de->name,MSDOS_DOT))
  402.                     ino = inode->i_ino;
  403.                 else if (!strcmp(de->name,MSDOS_DOTDOT))
  404.                      {
  405.                        ino = dmsdos_parent_ino(inode);
  406.                            if(ino<0)return ino;
  407.                          }
  408.                 /*bufname[i] = '\0'*/;
  409.                 put_fs_long(ino,&dirent->d_ino);
  410.                 memcpy_tofs(dirent->d_name,longname,i+1);
  411.                 put_fs_word(i,&dirent->d_reclen);
  412.                 
  413.                 return ROUND_UP(NAME_OFFSET(dirent) + i + 1);
  414.             }
  415.         }
  416.     }
  417.     return 0;
  418. }
  419.  
  420. #endif
  421.  
  422. int dmsdos_file_readx(
  423.     struct inode *inode,
  424.     struct file *filp,
  425.     char *buf,
  426.     int count)
  427. {      
  428.         int clusternr;
  429.         unsigned char*clusterd;
  430.         int cvfnr;
  431.         int offset;
  432.         int gelesen;
  433.         int membytes;
  434.         int ret;
  435.         char * b;
  436.         int toread;
  437.         char datum;
  438.         int need_cluster;
  439.  
  440.     if (!inode) {
  441.         printk("dmsdos_file_read: inode = NULL\n");
  442.         return -EINVAL;
  443.     }
  444.     /* S_ISLNK allows for UMSDOS. Should never happen for normal MSDOS */
  445.     if (!S_ISREG(inode->i_mode) && !S_ISLNK(inode->i_mode)) {
  446.         printk("dmsdos_file_read: mode = %07o\n",inode->i_mode);
  447.         return -EINVAL;
  448.     }
  449.  
  450.         cvfnr=(inode->i_ino>>DMSDOS_CVFNR_BITS)-1;
  451.         if(cvfnr<0)
  452.         { printk("DMSDOS: file_readx: invalid cvfnr ino=%ld\n",inode->i_ino);
  453.           return -EIO;
  454.         }
  455.         
  456.         if(count<=0)return 0;
  457.         
  458.         if(filp->f_pos>=inode->i_size)return 0;
  459.         
  460.         if(filp->f_pos+count>inode->i_size)count=inode->i_size-filp->f_pos;
  461.         
  462.         membytes=SECTOR_SIZE*dblsb[cvfnr].s_sectperclust;
  463.         
  464.         /* calculate clusternr for cluster to read */
  465.         clusternr=MSDOS_I(inode)->i_start;
  466.         offset=filp->f_pos;
  467.         while(offset>=membytes&&clusternr>0)
  468.         {  offset-=membytes;
  469.            clusternr=dbl_fat_nextcluster(inode->i_sb,clusternr,cvfnr,NULL);
  470.         }
  471.         if(clusternr<=0)
  472.         {  printk("DMSDOS: file_readx: FAT mismatches file size for ino=%ld\n",
  473.                    inode->i_ino);
  474.            return 0;        
  475.         }
  476.         
  477.         gelesen=0;
  478.         b=buf;
  479.         
  480.         clusterd=(unsigned char*)MALLOC(membytes);
  481.         if(clusterd==NULL)
  482.         { printk("DMSDOS: file_readx: no memory!\n");
  483.           return -EIO;
  484.         }
  485.         
  486.         if(MSDOS_I(inode)->i_binary==0)goto text_read;
  487.         
  488.         do
  489.         {  ret=dmsdos_read_cluster(inode->i_sb,clusterd,clusternr,cvfnr);
  490.            if(ret==0)
  491.            { toread=(membytes-offset>count) ? count : membytes-offset;
  492.              /*printk("DMSDOS file_readx: memcpy_tofs(0x%08x,0x%08x,0x%08x)\n",
  493.                      b,clusterd+offset,toread);*/
  494.              memcpy_tofs(b,clusterd+offset,toread);
  495.              gelesen+=toread;
  496.              count-=toread;
  497.              if(count>0)
  498.              { b+=toread;
  499.                offset=0;
  500.                clusternr=dbl_fat_nextcluster(inode->i_sb,clusternr,cvfnr,NULL);
  501.                if(clusternr<=0)
  502.                { ret=-1;
  503.                  printk("DMSDOS: file_readx: FAT mismatches file size for ino=%ld\n",
  504.                          inode->i_ino);
  505.                }
  506.              }
  507.            }
  508.         }
  509.         while(count>0&&ret==0);
  510.         
  511.         FREE(clusterd);
  512.         
  513.         filp->f_pos+=gelesen;
  514.         return gelesen;
  515.         
  516. text_read:
  517.         /* ok, let's do it byte for byte..... */
  518.         gelesen=0;
  519.         need_cluster=1;
  520.         while(count>0&&inode->i_size>filp->f_pos)
  521.         { if(need_cluster)
  522.           { ret=dmsdos_read_cluster(inode->i_sb,clusterd,clusternr,cvfnr);
  523.             if(ret<0)
  524.             { FREE(clusterd);
  525.               return -EIO;
  526.             }
  527.             clusternr=dbl_fat_nextcluster(inode->i_sb,clusternr,cvfnr,NULL);
  528.             need_cluster=0;
  529.           }
  530.  
  531.           datum=clusterd[offset++];
  532.  
  533.           ++(filp->f_pos);
  534.           if(datum!=13)
  535.           { put_fs_byte(datum,&(buf[gelesen]));
  536.             ++gelesen;
  537.             --count;
  538.           }
  539.           if(offset==membytes)
  540.           { need_cluster=1;
  541.             offset=0;
  542.           }
  543.         }
  544.         
  545.         FREE(clusterd);
  546.         return gelesen;
  547. }
  548.  
  549. int dmsdos_subdirs(struct inode*inode)
  550. { int cvfnr;
  551.   int startclust;
  552.   int ent=0;
  553.   int res=0;
  554.   unsigned char buf[32];
  555.   
  556.   /*printk("DMSDOS: subdirs, ino=%ld\n",inode->i_ino);*/
  557.   
  558.   if((cvfnr=dbltest(inode))!=0)cvfnr=(cvfnr>>DMSDOS_CVFNR_BITS)-1;
  559.   else cvfnr=(inode->i_ino>>DMSDOS_CVFNR_BITS)-1;
  560.   startclust=MSDOS_I(inode)->i_start;
  561.   
  562.   while(read_dbl_direntry(inode->i_sb,startclust,cvfnr,ent,buf)>0)
  563.   { ++ent;
  564.     if(buf[0]!=0xe5&&buf[0]!=0&&(buf[11]&0x10)!=0)++res;
  565.   }
  566.   return res;
  567. }
  568.  
  569. void dmsdos_read_inodex(struct inode *inode)
  570. {    
  571.         int dblsec;
  572.         int offs;
  573.         int cvfnr;
  574.         struct super_block *sb = inode->i_sb;
  575.     struct buffer_head *bh;
  576.     struct msdos_dir_entry *raw_entry;
  577.     int nr;
  578.     int zaehler;
  579.  
  580. /* printk("read inode %d\n",inode->i_ino); */
  581.     MSDOS_I(inode)->i_busy = 0;
  582.     MSDOS_I(inode)->i_depend = MSDOS_I(inode)->i_old = NULL;
  583.     MSDOS_I(inode)->i_binary = 1;
  584. #ifdef __FOR_KERNEL_1_3_8x
  585.         inode->i_uid = MSDOS_SB(inode->i_sb)->options.fs_uid;
  586.         inode->i_gid = MSDOS_SB(inode->i_sb)->options.fs_gid;
  587. #else
  588.     inode->i_uid = MSDOS_SB(inode->i_sb)->fs_uid;
  589.     inode->i_gid = MSDOS_SB(inode->i_sb)->fs_gid;
  590. #endif
  591.     if ((cvfnr=dbltest(inode))!=0) {
  592.             cvfnr=(cvfnr>>DMSDOS_CVFNR_BITS)-1;
  593.         inode->i_mode = ((S_IRUGO | S_IXUGO | 
  594.                ( /*dblsb[cvfnr].s_comp==READ_ONLY ? 0 :*/ S_IWUGO ) )& 
  595.                ~MSDOS_SB(inode->i_sb)->
  596. #ifdef __FOR_KERNEL_1_3_8x
  597.                              options.fs_umask
  598. #else
  599.                      fs_umask
  600. #endif
  601.                         ) | S_IFDIR;
  602.         inode->i_op = &dmsdos_dir_inode_operations;
  603.         MSDOS_I(inode)->i_start=0;/*muss bekannt sein fⁿr _subirs*/
  604.         inode->i_nlink = dmsdos_subdirs(inode)+2;
  605.             /* subdirs (neither . nor ..) plus . and "self" */
  606.         inode->i_size = dblsb[cvfnr].s_rootdiranzentry*
  607.             sizeof(struct msdos_dir_entry);
  608.         inode->i_blksize = dblsb[cvfnr].s_sectperclust*
  609.             SECTOR_SIZE;
  610.         inode->i_blocks = (inode->i_size+inode->i_blksize-1)/
  611.             inode->i_blksize*dblsb[cvfnr].s_sectperclust;
  612.         MSDOS_I(inode)->i_attrs = 0;
  613.         
  614.         /* read it */
  615.         if(!(bh=read_real_sector(inode->i_sb,inode->i_ino>>4)))
  616.         {
  617.             printk("dev = 0x%04X, ino = %ld\n",inode->i_dev,inode->i_ino);
  618.             panic("dmsdos_read_inode: unable to read i-node block");
  619.         }
  620.         raw_entry = &((struct msdos_dir_entry *) (bh->b_data))
  621.                               [inode->i_ino & (MSDOS_DPB-1)];
  622.         inode->i_mtime = inode->i_atime = inode->i_ctime = 
  623.                 date_dos2unix(CF_LE_W(raw_entry->time),
  624.                               CF_LE_W(raw_entry->date));
  625.         return;
  626.     }
  627.     
  628.     dblsec=(inode->i_ino&DMSDOS_ORIGINO_MASK)>>4;
  629.     offs=inode->i_ino&0xf;
  630.     cvfnr=(inode->i_ino>>DMSDOS_CVFNR_BITS)-1;
  631.  
  632.     if (!(bh = read_dbl_sector(inode->i_sb,dblsec,cvfnr))) {
  633.         printk("dev = 0x%04X, ino = %ld\n",inode->i_dev,inode->i_ino);
  634.         panic("dmsdos_read_inode: unable to read i-node block");
  635.     }
  636.     raw_entry = &((struct msdos_dir_entry *) (bh->b_data))
  637.         [inode->i_ino & (MSDOS_DPB-1)];
  638.     if ((raw_entry->attr & ATTR_DIR) && !IS_FREE(raw_entry->name)) {
  639. #ifdef __FOR_KERNEL_1_3_8x
  640.         inode->i_mode = MSDOS_MKMODE(raw_entry->attr,(S_IRUGO|S_IXUGO|
  641.                       (/*dblsb[cvfnr].s_comp==READ_ONLY ? 0 :*/ S_IWUGO) )
  642.                       & ~MSDOS_SB(inode->i_sb)->
  643.                             options.fs_umask
  644.                                  ) | S_IFDIR;
  645. #else
  646.         inode->i_mode = MSDOS_MKMODE(raw_entry->attr,(S_IRUGO|S_IXUGO|
  647.                       (/*dblsb[cvfnr].s_comp==READ_ONLY ? 0 :*/ S_IWUGO) )
  648.                       & ~MSDOS_SB(inode->i_sb)->
  649.                             fs_umask
  650.                                  ) | S_IFDIR;
  651. #endif
  652.         inode->i_op = &dmsdos_dir_inode_operations;
  653.         MSDOS_I(inode)->i_start = CF_LE_W(raw_entry->start);
  654.         inode->i_nlink = dmsdos_subdirs(inode);
  655.             /* includes .., compensating for "self" */
  656. #ifdef DEBUG
  657.         if (!inode->i_nlink) {
  658.             printk("directory %d: i_nlink == 0\n",inode->i_ino);
  659.             inode->i_nlink = 1;
  660.         }
  661. #endif
  662.         inode->i_size = 0;
  663.         
  664.         zaehler=0;
  665.         if ((nr = CF_LE_W(raw_entry->start)) != 0)
  666.             while (nr != -1) {
  667.                 inode->i_size += 
  668.                             dblsb[cvfnr].s_sectperclust*512;
  669.                 if (!(nr = dbl_fat_nextcluster(inode->i_sb,
  670.                                                nr,cvfnr,
  671.                                                NULL))) {
  672.                     printk("DMSDOS: readinodex: bad FAT (unexpected zero), ino=%ld\n",inode->i_ino);
  673.                     break;
  674.                 }
  675.                 
  676.                 ++zaehler;
  677.                 if(zaehler>65535)
  678.                 { printk("DMSDOS: read_inodex: loop in FAT, ino=%ld\n",inode->i_ino);
  679.                   break;
  680.                 }
  681.             }
  682.     }
  683.     else {
  684. #ifdef __FOR_KERNEL_1_3_8x
  685.         inode->i_mode = MSDOS_MKMODE(raw_entry->attr,((IS_NOEXEC(inode)
  686.             ? S_IRUGO : S_IRUGO|S_IXUGO) |
  687.                 (/*dblsb[cvfnr].s_comp==READ_ONLY ? 0 :*/ S_IWUGO) ) &
  688.                 ~MSDOS_SB(inode->i_sb)->
  689.                                options.fs_umask
  690.                          ) | S_IFREG;
  691. #else
  692.         inode->i_mode = MSDOS_MKMODE(raw_entry->attr,((IS_NOEXEC(inode)
  693.             ? S_IRUGO : S_IRUGO|S_IXUGO) |
  694.                 (/*dblsb[cvfnr].s_comp==READ_ONLY ? 0 :*/ S_IWUGO) ) &
  695.                 ~MSDOS_SB(inode->i_sb)->
  696.                        fs_umask
  697.                          ) | S_IFREG;
  698. #endif
  699.         inode->i_op = sb->s_blocksize == 1024
  700.             ? &dmsdos_file_inode_operations_1024
  701.             : &dmsdos_file_inode_operations;
  702.         MSDOS_I(inode)->i_start = CF_LE_W(raw_entry->start);
  703.         inode->i_nlink = 1;
  704.         inode->i_size = CF_LE_L(raw_entry->size);
  705.     }
  706.     MSDOS_I(inode)->i_binary = is_binary(MSDOS_SB(inode->i_sb)->
  707. #ifdef __FOR_KERNEL_1_3_8x
  708.                    options.conversion,
  709. #else              
  710.                conversion,
  711. #endif        
  712.         raw_entry->ext);
  713.     MSDOS_I(inode)->i_attrs = raw_entry->attr & ATTR_UNUSED;
  714.     /* this is as close to the truth as we can get ... */
  715.     inode->i_blksize = dblsb[cvfnr].s_sectperclust*SECTOR_SIZE;
  716.     inode->i_blocks = (inode->i_size+inode->i_blksize-1)/
  717.         inode->i_blksize*dblsb[cvfnr].s_sectperclust;
  718.     inode->i_mtime = inode->i_atime = inode->i_ctime =
  719.         date_dos2unix(CF_LE_W(raw_entry->time),CF_LE_W(raw_entry->date));
  720.     bh_free(inode->i_sb,bh);
  721.  
  722.         /*printk("DMSDOS: readinodex reading inode ino=%ld\n",inode->i_ino);*/
  723. }
  724.  
  725. int dmsdos_lookupx(struct inode *dir,const char *name,int len,
  726.     struct inode **result)
  727. {
  728.     int ino;
  729.     int cvfnr;
  730.     int startclust;
  731.     struct inode*next;
  732.     
  733.     PRINTK (("dmsdos_lookup\n"));
  734.  
  735.     *result = NULL;
  736.     if (!dir) return -ENOENT;
  737.     if (!S_ISDIR(dir->i_mode)) {
  738.         iput(dir);
  739.         return -ENOENT;
  740.     }
  741.     PRINTK (("dmsdos_lookup 2\n"));
  742.     if (len == 1 && name[0] == '.') {
  743.         *result = dir;
  744.         return 0;
  745.     }
  746.     if (len == 2 && name[0] == '.' && name[1] == '.') {
  747.             if(dbltest(dir))
  748.             { /*printk("DMSDOS: lookupx '..' result MDSOS_ROOT\n");*/
  749.               ino=MSDOS_ROOT_INO;
  750.             }
  751.         else
  752.         { /*printk("DMSDOS: lookupx '..' inode ino=%ld\n",dir->i_ino);*/
  753.           ino=dmsdos_parent_ino(dir);
  754.         }
  755.         iput(dir);
  756.         if (ino < 0) return ino;
  757.         if (!(*result = iget(dir->i_sb,ino))) return -EACCES;
  758.         return 0;
  759.     }
  760.     if((cvfnr=dbltest(dir))!=0)cvfnr=(cvfnr>>DMSDOS_CVFNR_BITS)-1;
  761.     else cvfnr=(dir->i_ino>>DMSDOS_CVFNR_BITS)-1;
  762.     startclust=MSDOS_I(dir)->i_start;/*dbl_inode2startcluster(dir);*/
  763.     ino=scan_dbl_dir_4_lfn(dir->i_sb,startclust,name,len,cvfnr,NULL);
  764.     if(ino<0)
  765.     { iput(dir);
  766.       return ino;
  767.     }
  768.     if(!(*result=iget(dir->i_sb,ino))) return -EACCES;
  769.     
  770.     PRINTK (("dmsdos_lookup 5\n"));
  771.     if (MSDOS_I(*result)->i_busy) { /* mkdir in progress */
  772.         iput(*result);
  773.         iput(dir);
  774.         return -ENOENT;
  775.     }
  776.     PRINTK (("dmsdos_lookup 6\n"));
  777.     while (MSDOS_I(*result)->i_old) {
  778.         next = MSDOS_I(*result)->i_old;
  779.         iput(*result);
  780.         if (!(*result = iget(next->i_sb,next->i_ino))) {
  781. #ifdef __FOR_KERNEL_1_3_8x
  782.             fat_fs_panic(dir->i_sb,"msdos_lookup: Can't happen");
  783. #else
  784.             fs_panic(dir->i_sb,"msdos_lookup: Can't happen");
  785. #endif
  786.             iput(dir);
  787.             return -ENOENT;
  788.         }
  789.     }
  790.     PRINTK (("dmsdos_lookup 7\n"));
  791.     iput(dir);
  792.     PRINTK (("dmsdos_lookup 8\n"));
  793.     return 0;
  794. }
  795.